package com.study;

import com.querydsl.core.types.dsl.BooleanExpression;
import com.study.entity.QStudent;
import com.study.entity.Student;
import com.study.repository.QueryDSLRepository;
import com.study.repository.StudentRepository;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.*;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * @Classname SpringDtoStudent
 * @Version 1.0.0
 * @Date 2022/4/2 23:35
 * @Created by yd
 */
@Slf4j
@SpringBootTest
public class SpringDtoStudent {
	@Autowired
	QueryDSLRepository queryDSLRepository;
	@Autowired
	private StudentRepository studentRepository;

	@Test
	public void addStudent() {
		for (int i = 0; i < 10; i++) {
			studentRepository.save(new Student().setBirthTime(LocalDateTime.now()).setName("nam" + i));

		}
	}

	//上面是lambda的写法

	@Test
	public void findSpec() {
		/**
		 * 1 查询方式 cb对象
		 * 2 比较的属性名称 root对象
		 */
		Specification<Student> spec = (root, query, cb) -> {
			// 1 获取比较比较的属性
			Path name = root.get("name");
			// 2 构造查询条件
			return cb.equal(name, "nam2");
		};
		Optional<Student> one = studentRepository.findOne(spec);
		System.out.println(one.orElse(new Student()));
	}

	@Test
	public void findSpecAnd() {
		/**
		 * 1 查询方式 cb对象
		 * 2 比较的属性名称 root对象
		 */
		Specification<Student> spec = new Specification<Student>() {
			@Override
			public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
				// 1 获取比较比较的属性
				Path name = root.get("name");
				// 2 构造查询条件
				Predicate predicate = cb.equal(name, "nam1");

				Path id = root.get("id");
				Predicate idPredicate = cb.equal(id, 1L);

				//多个条件组合
				// 1 以 and的形式拼接起来
				// Predicate and = cb.and(predicate, idPredicate);
				Predicate resultPredicate = cb.or(predicate, idPredicate);
				return resultPredicate;
			}
		};
		List<Student> list = studentRepository.findAll(spec);
		list.forEach(System.out::println);

	}

	@Test
	public void findSpecLike() {
		/**
		 * 1 查询方式 cb对象
		 * 2 比较的属性名称 root对象
		 * 3 query 组合 (order by ,where)
		 */
		Specification<Student> spec = new Specification<Student>() {
			@Override
			public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
				// 1 获取比较比较的属性
				Path name = root.get("name");
				// 2 构造查询条件
				Predicate predicate = cb.like(name, "nam1");

				Path id = root.get("id");
				Predicate idPredicate = cb.gt(id, 1L);

				//多个条件组合
				// 1 以 and的形式拼接起来
				// Predicate and = cb.and(predicate, idPredicate);
				Predicate resultPredicate = cb.or(predicate, idPredicate);
				return resultPredicate;
			}
		};
		List<Student> list = studentRepository.findAll(spec);
		list.forEach(System.out::println);
	}

	/**
	 * 分页查询
	 */
	@Test
	public void findPage() {
		Pageable pageable = PageRequest.of(0, 2);
		Page<Student> page = studentRepository.findAll(pageable);
		System.out.println(page);
		int totalPages = page.getTotalPages();
		System.out.println("总数量" + page.getTotalElements());

	}

	/**
	 * 排序不用硬编码
	 * https://docs.gitcode.net/spring/guide/spring-data/spring-data.html#_4-4-%E5%AE%9A%E4%B9%89%E6%9F%A5%E8%AF%A2%E6%96%B9%E6%B3%95
	 * <p>
	 * 硬编码
	 * Sort sort = Sort.by("firstname").ascending()
	 * .and(Sort.by("lastname").descending());
	 * </p>
	 * 使用类型安全的API定义排序
	 * <code>
	 * TypedSort<Person> person = Sort.sort(Person.class);
	 * Sort sort = person.by(Person::getFirstname).ascending()
	 * .and(person.by(Person::getLastname).descending());
	 * </code>
	 * <p>
	 */
	@Test
	public void findSort() {
		//硬编码的方式排序
		Sort sort = Sort.by("firstname").ascending()
				.and(Sort.by("lastname").descending());

		//使用类型安全的API定义排序表达式
		Sort.TypedSort<Student> stuSort = Sort.sort(Student.class);
		Sort sortApi = stuSort.by(Student::getId).descending()
				.and(stuSort.by(Student::getBirthTime).ascending());

		List<Student> all = studentRepository.findAll(sortApi);
		System.out.println(all);
	}

	@Test
	public void findByName() {
		//getStudent
		List<Student> li = studentRepository.getStudent("nam1");
		System.out.println(li);
	}

	@Test
	public void jpaUpdate() {
		System.out.println(studentRepository.updateStudent("nam1", 1L));
	}

	@Test
	public void queryByExampleExecutor() {
		Student student = new Student().setName("nam1").setId(1L);
		Example<Student> example = Example.of(student);

		List<Student> all = studentRepository.findAll(example);
	}


	@Test
	public void queryDsl() {
		QStudent student = QStudent.student;
		BooleanExpression eq = student.id.eq(1L);
		Optional<Student> one = queryDSLRepository.findOne(eq);
		System.out.println(one.get());
	}

	@Test
	public void queryDsl2() {
		QStudent student = QStudent.student;

		BooleanExpression and = student.name.in("nam1", "nam2")
				.and(student.id.gt(1L));

		BooleanExpression gt = student.id.gt(1L);
		BooleanExpression or = and.or(gt);
		Iterable<Student> all = queryDSLRepository.findAll(or);

	}

	@Test
	public void queryJpaSpec() {

	}
}
